﻿using Application.Common.Interfaces;
using Application.Features.Roles.EventHandlers;
using Common.Attributes;
using Common.Enums;
using Common.Services;
using Domain.Entities;
using Domain.Entities.Identity;
using MediatR;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace Application.Features.Roles.Commands.Update;

/// <summary>
/// 分配权限
/// </summary>
[Description("分配权限")]
[GroupDescription(("角色管理"))]
public class AssignMenuToRoleCommand : IRequest<bool>
{
    /// <summary>
    /// 角色唯一标识
    /// </summary>
    [Required(ErrorMessage = "角色唯一标识必填")]
    public long RoleId { get; set; }

    /// <summary>
    /// 菜单唯一标识
    /// </summary>
    [Required(ErrorMessage = "唯一标识必填")]
    public List<long>? MenuIds { get; set; }
}

/// <summary>
/// 处理程序
/// </summary>
public class AssignMenuToRoleCommandHandler : IRequestHandler<AssignMenuToRoleCommand, bool>
{
    private readonly IApplicationDbContext _context;
    private readonly ISnowFlakeService _snowFlakeService;
    private readonly IMediator _mediator;

    public AssignMenuToRoleCommandHandler(
        IApplicationDbContext context,
        ISnowFlakeService snowFlakeService,
        IMediator mediator)
    {
        _context = context;
        _snowFlakeService = snowFlakeService;
        _mediator = mediator;
    }

    /// <summary>
    /// 业务逻辑
    /// </summary>
    /// <param name="request">请求参数</param>
    /// <param name="cancellationToken">取消标记</param>
    /// <returns>返回处理结果</returns>
    public async Task<bool> Handle(AssignMenuToRoleCommand request, CancellationToken cancellationToken)
    {
        var roleMenusToDelete = await _context.RoleMenus
            .Include(r => r.Role)
            .Where(x => x.RoleId == request.RoleId).ToListAsync(cancellationToken);
        if (roleMenusToDelete.Any()) 
        {
            await _mediator.Publish(new AssignMenuToRoleEvent<Role>(roleMenusToDelete.First().Role));
            _context.RoleMenus.RemoveRange(roleMenusToDelete);
        }

        var roleMenus=new List<RoleMenu>();
        foreach (var menuId in request.MenuIds!) 
        {
            roleMenus.Add(new RoleMenu
            {
                Id = _snowFlakeService.GenerateId(),
                RoleId = request.RoleId,
                MenuId = menuId
            });
        }

       await _context.RoleMenus.AddRangeAsync(roleMenus);

        return true;
    }
}